home *** CD-ROM | disk | FTP | other *** search
/ Languguage OS 2 / Languguage OS II Version 10-94 (Knowledge Media)(1994).ISO / language / embedded / mcu11 / ffthc11.arc / FFTHC11.ASM
Assembly Source File  |  1987-01-29  |  13KB  |  377 lines

  1. * fft.c11 - fast fourier transform for the MC68HC11
  2. *        written by:
  3. *
  4. *        Ron Williams
  5. *        Department of Chemistry
  6. *        Ohio University
  7. *        Athens, OH 45701
  8. *
  9. * This is a modification of the 6800 FFT presented by:
  10. *      Richard Lord
  11. *      Byte Magazine, pp. 108-119
  12. *      February 1979
  13. *
  14. * My version is written in ROMable code for the HC11. 
  15. * It uses a sine look-up table for speed and can only 
  16. * transform 256 8-bit data points.  The program 
  17. * assumes that the address of the real data is pushed 
  18. * on the stack prior to the call and that a 256 byte 
  19. * imaginary buffer is at data+256 therefore you must 
  20. * declare a 512 byte data array in the calling routine 
  21. * and load the lower 256 bytes with data.  The FFT 
  22. * will zero out the imaginary portion.  Also note that 
  23. * the FFT uses memory in the stack RAM for its dynamic 
  24. * variables and the FFT returns a value on the stack 
  25. * which contains the number of times the data was 
  26. * divided by 2 during transform. 
  27. * As mentioned in Lord's article, "power" spectra can 
  28. * be computed using the sum of absolute values routine 
  29. * included at the end of the FFT. Simply change the 
  30. * beq done at the end of the FFT to beq smsq. 
  31. * note - this copy has been modified to use $DD00 for 
  32. * data because this is easiest with BUFFALO
  33. * I have timed this transform on some test data.  The 
  34. * results are an impressive 350 milliseconds per 
  35. * transform including the "power" spectra computation. 
  36. * Please note that the origin of this code may require 
  37. * adjustment for your specific memory map. 
  38. * Please let me know of any bugs you find.
  39.  
  40. return  equ     0
  41. real    equ     2
  42. celnm   equ     4
  43. celct   equ     5
  44. pairnm  equ     6
  45. celdis  equ     7
  46. delta   equ     8
  47. sclfct  equ     9
  48. cosa    equ     $0A
  49. sina    equ     $0B
  50. sinpt   equ     $0C
  51. real1   equ     $0E
  52. real2   equ     $10
  53. treal   equ     $12
  54. timag   equ     $13
  55. tmp     equ     $14
  56. tmp2    equ     $15
  57. data    equ     $DD00
  58.  
  59.         org     $C000
  60.  
  61.         tsx             top of stack for frame pointer
  62.         xgdx                to be placed in X
  63.         subd    #$18    subtract offset to make room
  64.         xgdx            X now has frame pointer
  65.         puly            get return address
  66.         sty     return,X save it
  67. *        puly            get data address
  68. *        sty     real,X  save it
  69.         ldy    #data
  70.         sty    real,X
  71.         clr     sclfct,X zero scale factor
  72.         iny             inc y for imag data
  73.         clrb
  74. zero    clr     $FF,Y   note special place of imag
  75.         iny              256 above data
  76.         decb
  77.         bne     zero
  78. *
  79. * must do bit sorting before transforming
  80. *
  81.         ldab    #$FE    setup start for bit reversal
  82. revbit  ldaa    #08     get # of bits to reverse
  83.         pshb            save address offset
  84. rev1    rorb            rotate b right - bit to carry
  85.         rol     tmp,X   rotate left - carry bit in
  86.         deca            decrement counter
  87.         bne     rev1    go back if not done
  88.         pulb            get unshifted address
  89.         pshb            save copy
  90.         cmpb    tmp,X   check to see if already done
  91.         bcs     noswap  if so don't swap bytes
  92. swap    ldy     real,X  get data address
  93.         aby             add to base address
  94.         ldaa    0,Y     get value
  95.         pshy            store away
  96.         ldy     real,X  get base again
  97.         ldab    tmp,X   get shifted address
  98.         aby             add to base
  99.         ldab    0,Y     get second member
  100.         staa    0,Y     put away first member
  101.         puly            get first address
  102.         stab    0,Y     put second member in first slot
  103. noswap  pulb            get current address back
  104.         decb            decrement it
  105.         bne     revbit  do next if not done
  106. *
  107. * special case of first pass of FFT
  108. *
  109.         jsr     scale
  110.         ldy     real,X  set up data pointer
  111.         ldaa    #128    get number of cells
  112.         staa    tmp,X   store in temp
  113. fpss    ldaa    0,Y     get RM
  114.         ldab    1,Y     get RN
  115.         psha            make copy
  116.         aba             RM'=RM+RN
  117.         staa    0,Y     save back in data array
  118.         pula            get RM again
  119.         sba             RN'=RM-RN
  120.         staa    1,Y     put away
  121.         iny             point to next pair
  122.         iny
  123.         dec     tmp,X   decrement # cells
  124.         bne     fpss    go back if not done
  125. *
  126. * now the FFT proper for passes 2 thru N
  127. *
  128. four    ldaa    #64     # of cells is now 64
  129.         staa    celnm,X store
  130.         staa    delta,X so is delta
  131.         ldaa    #02     number of pairs is 2
  132.         staa    pairnm,X
  133.         staa    celdis,X so is distance between
  134. npass   jsr     scale   check for over-range
  135.         ldaa    celnm,X get current cell #
  136.         staa    celct,X store at cell counter
  137.         ldy     real,X
  138.         sty     real1,X get copy of data
  139. ncell   ldy     #sintab get address of sines
  140.         sty     sinpt,X save copy
  141.         ldaa    pairnm,X get current pairnm
  142. np1     psha            save pair counter
  143.         ldaa    0,Y     get cosine
  144.         ldab    64,Y    get sine
  145.         staa    cosa,X  save copy
  146.         stab    sina,X  ditto
  147.         ldy     real1,X point to top of data
  148.         ldab    celdis,X get current offset
  149.         aby             add to Y for current 
  150.         sty     real2,X copy it
  151.         ldaa    0,Y     get data point rn
  152.         psha            copy it
  153.         ldab    cosa,X  get cosine
  154.         jsr     smul    rn*cos(a)
  155.         staa    treal,X
  156.         pula            get copy of rn
  157.         ldab    sina,X  get sin(a)
  158.         jsr     smul    rn*sin(a)
  159.         staa    timag,X store imaginary tmp
  160.         iny
  161.         ldaa    $FF,Y   get imaginary data
  162.         psha            save it
  163.         ldab    sina,X  get sin(a)
  164.         jsr     smul    in*sin(a)
  165.         adda    treal,X
  166.         staa    treal,X  tr=rn*cos + in*sin
  167.         pula            get data back
  168.         ldab    cosa,X  get cosine
  169.         jsr     smul    in*cos(a)
  170.         suba    timag,X  ti=in*cos-rn*sin
  171.         staa    timag,X
  172.         ldy     real1,X
  173.         ldaa    00,Y    get rm 
  174.         tab             save a copy
  175.         adda    treal,X rm'=rm+tr
  176.         staa    00,Y    store new rm
  177.         subb    treal,X rn'=rm-tr
  178.         ldy     real2,X
  179.         stab    00,Y    store new rn
  180.         ldy     real1,X
  181.         iny
  182.         sty     real1,X save real1 for nxt
  183.         ldaa    $FF,Y   get im
  184.         tab             save copy
  185.         adda    timag,X im'=im+ti
  186.         staa    $FF,Y   put back in array
  187.         ldy     real2,X
  188.         iny
  189.         subb    timag,X in'=im-ti
  190.         stab    $FF,Y   put back in array
  191.         ldy     sinpt,X
  192.         ldab    delta,X increment sine pntr
  193.         aby
  194.         sty     sinpt,X save away
  195.         pula
  196.         deca            dec pair counter
  197.         bne     np1
  198. ar1     ldy     real1,X
  199.         ldab    celdis,X
  200.         aby
  201.         sty     real1,X
  202.         dec     celct,X
  203.         beq     ar3
  204.         jmp     ncell
  205. ar3     lsr     celnm,X  half cells
  206.         beq     smsq    done when all cells
  207.         asl     pairnm,X double pairs
  208.         asl     celdis,X twice as far apart
  209.         lsr     delta,X  delta is half
  210.         jmp     npass    one more time!
  211. done    ldaa    sclfct,X get scale factor
  212.         psha             save on stack
  213.         ldy     return,X
  214.         pshy
  215.         rts
  216. *
  217. * sum of absolute values instead of sum of squares
  218. *
  219. smsq    ldy     real,X   compute sum of "sqrs"
  220.         clra             clear byte counter
  221. sum     psha             save on stack
  222.         ldaa    0,Y      get real data point
  223.         bpl     sm1      force positive
  224.         nega
  225.         bvc     sm1      watch for $80
  226.         clra               which is really 0
  227. sm1     iny              get imaginary data
  228.         ldab    $FF,Y
  229.         bpl     sm2      force positive
  230.         negb
  231.         bvc     sm2      watch for $80 again
  232.         clrb
  233. sm2     dey              correct data pointer
  234.         aba              compute sum
  235.         staa    0,Y      save back in real
  236.         iny              inc Y for next round
  237.         pula             get byte counter
  238.         deca             done when zero
  239.         bne     sum
  240.         bra     done     lets get out of here
  241. *
  242. * subroutine for catching overscaled data
  243. *
  244. scale   ldy     real,X   start at top of data
  245.         ldab    #$FF
  246.         aby              top of data
  247.         aby              top or imag
  248.         iny              need two more
  249.         iny
  250.         ldaa    #$C0     -64
  251.         ldab    #$40     +64
  252. top     cmpa    0,Y      check for minimum
  253.         blo     nxt      if more negative fix
  254.         cmpb    0,Y      check for too big
  255.         bcs     scl      go fix it
  256. nxt     dey              bump pointer
  257.         cpy  real,X      done when both
  258.         bne     top      imag and data done
  259.         rts
  260. scl     inc     sclfct,X keep track of scale
  261.         ldy     real,X   set up pointer
  262.         ldab    #$FF
  263.         aby
  264.         aby
  265.         iny
  266.         iny
  267. scl1    ldaa    0,Y      get data
  268.         adda    #$80     make positive
  269.         lsra             divide by two
  270.         suba    #$40     put back
  271.         staa    0,Y      store away
  272.         dey              bump pointer
  273.         cpy     real,X   done when both
  274.         bne     scl1     imag and data done
  275.         rts
  276. *
  277. * the HC11 multiply must be modified to handle
  278. * negative data
  279. *
  280. smul    staa    tmp,X   copy multiplier
  281.         stab    tmp2,X  ditto multiplicand
  282.         tsta            check sign of multiplier
  283.         bpl     sk1     skip negation
  284.         nega
  285.         bvs     sko     check for $80
  286.         beq     sko     check for zero
  287. sk1     tstb            check multiplier sign
  288.         bpl     sk2
  289.         negb
  290.         bvs     sko     check for $80
  291.         beq     sko
  292. sk2     mul             do multiplication
  293.         adca    #0      8 bit conversion
  294.         asla            and correct for sine
  295.         ldab    tmp2,X  get original multiplicand
  296.         eorb    tmp,X   check for result
  297.         bpl     out
  298.         nega            result is negative
  299. out     rts
  300. sko     clra            return zero to main
  301.         rts
  302. *
  303. * now for the sine look up table
  304. *
  305. sintab            
  306.  fcb  127, 127, 127, 127, 126, 126, 126, 125, 125, 124
  307.  fcb  123, 122, 122, 121, 120, 118, 117, 116, 115, 113
  308.  fcb  112, 111, 109, 107, 106, 104, 102, 100,  98,  96
  309.  fcb   94,  92,  90,  88,  85,  83,  81,  78,  76,  73
  310.  fcb   71,  68,  65,  63,  60,  57,  54,  51,  49,  46
  311.  fcb   43,  40,  37,  34,  31,  28,  25,  22,  19,  16
  312.  fcb   12,   9,   6,   3,   0,  -3,  -6,  -9, -12, -16
  313.  fcb  -19, -22, -25, -28, -31, -34, -37, -40, -43, -46
  314.  fcb  -49, -51, -54, -57, -60, -63, -65, -68, -71, -73
  315.  fcb  -76, -78, -81, -83, -85, -88, -90, -92, -94, -96
  316.  fcb  -98,-100,-102,-104,-106,-107,-109,-111,-112,-113
  317.  fcb -115,-116,-117,-118,-120,-121,-122,-122,-123,-124
  318.  fcb -125,-125,-126,-126,-126,-127,-127,-127,-127,-127
  319.  fcb -127,-127,-126,-126,-126,-125,-125,-124,-123,-122
  320.  fcb -122,-121,-120,-118,-117,-116,-115,-113,-112,-111
  321.  fcb -109,-107,-106,-104,-102,-100, -98, -96, -94, -92
  322.  fcb  -90, -88, -85, -83, -81, -78, -76, -73, -71, -68
  323.  fcb  -65, -63, -60, -57, -54, -51, -49, -46, -43, -40
  324.  fcb  -37, -34, -31, -28, -25, -22, -19, -16, -12,  -9
  325.  fcb   -6,  -3,   0,   3,   6,   9,  12,  16,  19,  22
  326.  fcb   25,  28,  31,  34,  37,  40,  43,  46,  49,  51
  327.  fcb   54,  57,  60,  63,  65,  68,  71,  73,  76,  78
  328.  fcb   81,  83,  85,  88,  90,  92,  94,  96,  98, 100
  329.  fcb  102, 104, 106, 107, 109, 111, 112, 113, 115, 116
  330.  fcb  117, 118, 120, 121, 122, 122, 123, 124, 125, 125
  331.  fcb  126, 126, 126, 127, 127, 127
  332. *
  333. * Some routines for fast A2D and for sending data to 
  334. * host
  335. *   these have not been debugged
  336. *
  337. chan4   equ     $04
  338. atdctr  equ     $1030
  339. portc   equ     $1003
  340. ccontr  equ     $1002
  341. lportc  equ     $1005
  342. strt    equ     $02
  343.         ldy     #data
  344.         ldaa    #chan4
  345.         ldab    #strt
  346. wait:   bitb    portc
  347.         beq     wait
  348. cklp:   ldab    ccontr
  349.         bpl     cklp
  350.         staa    atdctr
  351.         ldab    lportc
  352.         iny
  353.         cpy     #data+256
  354.         beq     adone
  355.         nop
  356.         nop
  357.         nop
  358.         nop
  359.         ldab    atdctr+1
  360.         stab    $00,Y
  361.         bra     cklp
  362. adone:  rts
  363.  
  364. output  equ    #$E3B3
  365. sendat  ldx    #data
  366.         clrb
  367. s1      jsr    output
  368.         decb
  369.         bne    s1
  370.         rts
  371.  
  372.  
  373. ut  equ    #$E3B